import { filter_structure ,LeastHit} from '@/utils'
import creep from '.'

export default class CreepExtension extends Creep {

    /* ---------------------进阶【通用】函数接口----------------------- */
    /* A型 -> Auto 自动型，无参数无返回值 C型 -> Control 控制型，有参数无返回值  */
    /* 采集通用函数 */

    /*
    ** A型1号  注【仅用于spawn房间内】逻辑 --->
    ** 1.获取房间的资源点数量
    ** 2.如果没有资源则通报异常，1个资源点和2个资源点分开处理
    ** --(1)1个资源点则将开采目标定位该资源点,并将资源点ID存入爬虫的记忆里
    ** --(2)2个资源点则选择距离controller较远的资源点作为开采目标,并将资源点ID存入爬虫的记忆里
    ** 3.开采完后将资源点放入空的巢穴和扩展中，如果都满了将寻找storage,将能量存入storage中，无storage则寻找建筑并执行建造任务，否则前往虫卵附近待命
    */
    public harvest_A1():void{
        this.farsourceID()
        if (this.memory.sourceId && this.memory.sourceId != 'no source')
        {
            this.workstate(RESOURCE_ENERGY)
            if (this.memory.working)
            {
                // 寻找没满的虫卵和扩展
                var spawn_extension:Structure = this.pos.getClosestStore()
                if (spawn_extension)
                {
                    this.transfer_(spawn_extension,RESOURCE_ENERGY)
                }
                else{
                    // 如果都满了，考虑storage
                    //if (!this.memory.sourceId)
                    var storage_ = this.pos.getClosestStructure([STRUCTURE_STORAGE],0) as StructureStorage
                    var tower = this.pos.findClosestByRange(FIND_STRUCTURES,{filter:(st)=>{
                        return st.structureType == STRUCTURE_TOWER && st.store.getFreeCapacity(RESOURCE_ENERGY) > 0
                    }}) as StructureTower
                    if (tower && (!storage_ || (storage_ && storage_.my) ))
                    {
                        this.transfer__(tower,RESOURCE_ENERGY)
                        return
                    }
                    if (storage_ &&storage_.my){
                        this.transfer__(storage_,RESOURCE_ENERGY)
                    }
                    else{
                        // 如果没有sotrage了那就寻找建筑工地
                        var construction_:ConstructionSite = this.pos.findClosestByRange(FIND_CONSTRUCTION_SITES)
                        if (construction_) {this.build__(construction_)}
                        else{
                            // 如果虫卵扩展都填好了、尿壶也没有、建筑工地也搞完了，就取升级控制器
                            this.upgrade__()
                        }
                    }
                }
            }
            else
            {
                this.harvest__(Game.getObjectById(this.memory.sourceId))
            }
        }
    }
    /*
    ** A型2号  注【仅用于spawn房间内】逻辑 --->
    ** 1.获取房间的资源点数量
    ** 2.如果没有资源则通报异常，1个资源点和2个资源点分开处理
    ** --(1)1个资源点则将开采目标定位该资源点,并将资源点ID存入爬虫的记忆里
    ** --(2)2个资源点则选择距离controller较远的资源点作为开采目标,并将资源点ID存入爬虫的记忆里
    ** 3.开采完后将资源点放入Link中,没有link或者Link资源满了就进入A1模式
    */
    public harvest_A2():void{
        this.farsourceID()
        if (this.memory.sourceId && this.memory.sourceId != 'no source')
        {
            // 有sourceId就开始干活了
            this.workstate(RESOURCE_ENERGY)
            if (this.memory.working)
            {
                var dis_source = Game.getObjectById(this.memory.sourceId) as Source
                var dis_link = dis_source.pos.getClosestStructure([STRUCTURE_LINK],0)
                if (dis_link)
                {
                    this.transfer__(dis_link,RESOURCE_ENERGY)
                }
            }
            else{
                this.harvest__(Game.getObjectById(this.memory.sourceId))
                let ds = this.pos.findInRange(FIND_DROPPED_RESOURCES,1)
                if (ds.length > 0)
                {
                    if (ds[0].resourceType == RESOURCE_ENERGY && ds[0].amount > 10)
                    this.pickup(ds[0])
                }
            }
        }
    }

    /* 建造通用函数 */
    /*
    ** A型1号 注【仅用于spawn房间内】逻辑 --->
    ** 1. 采集资源 工作地点10格内有storage就去storage，否则优先寻找最近的 link/container/source进行采集
    ** 2. 进行工作按照优先级分为(1)和(2)两个优先级
    ** --(1) 首要任务是执行除墙体/小仓库之外建筑的修复，道路在低于0.6后会进行修复。其他建筑一样，按照优先级首先修复 spawn/terminal/tower
    ** --(2) 在没有紧急修复要求的情况下，寻找建筑差事，并着手建筑
    ** 3. 在无须修复和建筑的时候，化身为upgrader
    */
    public vindicat_A1():void{
        // 首先寻找优先目标 不包括wall/container/road/rampart
        var distination:Structure | ConstructionSite | undefined
        var package_structure:StructureConstant[] = [STRUCTURE_SPAWN,STRUCTURE_POWER_SPAWN,STRUCTURE_LINK,
            STRUCTURE_EXTENSION,STRUCTURE_TOWER,STRUCTURE_LAB,STRUCTURE_FACTORY,STRUCTURE_NUKER,STRUCTURE_OBSERVER]
        var repair_distination:Structure[] = this.room.find(FIND_STRUCTURES,{filter:(structure)=>{return filter_structure(structure,package_structure) && structure.hits < structure.hitsMax}})
        if (repair_distination.length > 0){
            // 如果存在hits不正常的核心structure，则找到差值最大的建筑进行修复
            distination = LeastHit(repair_distination,1)
        }
        else{
            // 寻找hits/hitsMax比小于0.6的road
            var road_structure:Structure[] = this.room.find(FIND_STRUCTURES,{filter:(structure)=>{return filter_structure(structure,[STRUCTURE_ROAD]) && structure.hits < structure.hitsMax}})
            if (road_structure.length > 0)
            {
                var sample_value = LeastHit(road_structure,2,0.5)
                if (sample_value) distination = sample_value
                else
                {
                    // 在不满足以上情况，则寻找construction
                    var construction:ConstructionSite = this.pos.findClosestByRange(FIND_CONSTRUCTION_SITES)
                    if (construction)
                    {
                        distination = construction
                    }
                    else
                    {
                        distination = undefined
                    }
                }
            }
            else
                {
                    // 在不满足以上情况，则寻找construction
                    var construction:ConstructionSite = this.pos.findClosestByRange(FIND_CONSTRUCTION_SITES)
                    if (construction)
                    {
                        distination = construction
                    }
                    else
                    {
                        distination = undefined
                    }
                }
        }
        // 执行任务部分
        this.workstate(RESOURCE_ENERGY)
        if (this.memory.working)
        {
            if (distination instanceof Structure) this.repair__(distination)
            if (distination instanceof ConstructionSite) this.build__(distination)
            if (distination == undefined) this.upgrade__()
        }
        else
        {
            // 如果目标存在
            if (distination)
            {
                var source_ : Structure | Source
                // 判断目标十格范围内是否有storage
                var storage_ = distination.pos.findInRange(FIND_STRUCTURES,30,{filter:(structure)=>{return structure.structureType == STRUCTURE_STORAGE && structure.store.getUsedCapacity(RESOURCE_ENERGY) >= this.store.getCapacity()}})
                if (storage_.length > 0) source_ = storage_[0]
                else{
                    // 判断5格内是否有 Link/container
                    var link_ = distination.pos.findInRange(FIND_STRUCTURES,5,{filter:(structure)=>{
                        return (structure.structureType == STRUCTURE_CONTAINER || structure.structureType == STRUCTURE_LINK) && structure.store.getUsedCapacity(RESOURCE_ENERGY) >= this.store.getCapacity()
                    }})
                    if (link_.length > 0 ) source_ = link_[0]
                    else
                    {
                        // 否则就寻找离建筑物最近的建筑
                        source_ = distination.pos.findClosestByRange(FIND_SOURCES)
                    }
                }
            }
            else{
                // source_ =  this.pos.findClosestByRange(FIND_SOURCES)
                source_ = null
            }
            if (source_ instanceof Source) this.harvest__(source_)
            if (source_ instanceof Structure) this.withdraw__(source_,RESOURCE_ENERGY)
        }
    }

    /* 物流通用函数 */
    /*
    ** A型1号  注【仅用于spawn房间内】逻辑 --->
    **  1. 从storage中提取资源
    **  2.将资源填满所有空的扩展，注意生命周期，生命过低则不提取，如果都满了，并且creep体内还有能量，则将能量返还给storage
    */
    public transport_A1():void{
        if (!this.memory.StorageId)
            this.memory.StorageId = this.gainStoreStructure(STRUCTURE_STORAGE,RESOURCE_ENERGY).id
        var storage_ = Game.getObjectById(this.memory.StorageId) as StructureStorage
        if (!storage_) return
        // 寻找所有有空缺的扩展和虫卵,lab
        var spawn_extension:Structure = this.pos.getClosestStore()
        this.workstate(RESOURCE_ENERGY)
        if (this.memory.working && spawn_extension)
        {
            this.transfer__(spawn_extension,RESOURCE_ENERGY)
        }
        if (this.memory.working && !spawn_extension)
        {
            // 填充核弹
            var nuke = this.pos.getClosestStructure([STRUCTURE_NUKER],0) as StructureNuker
            if (nuke && nuke.store.getFreeCapacity(RESOURCE_ENERGY) > 0)
            {
                this.transfer__(nuke,RESOURCE_ENERGY)
            }
        }
        if (!this.memory.working)
        {
            this.withdraw__(storage_,RESOURCE_ENERGY)
        }
        this.LastMisson(10)
    }

    /* 涂墙通用函数 */
    /*
    ** A型1号 注【仅试用于自动规划1型】
    ** 寻找核心周围的墙体和rampart进行维修
    */
    public repair_A1():void{
        this.workstate(RESOURCE_ENERGY)
        if (this.memory.working)
        {
            // 定义中心点
            var position_ = new RoomPosition(this.room.memory.center_x+2,this.room.memory.center_y,this.room.name)
            var wall_ = position_.getRangedStructure([STRUCTURE_RAMPART],8,2)
            if (wall_)
            {
                this.repair__(wall_ as Structure)
            }
            else
            {
                this.upgrade__()
            }
        }
        else
        {
            var storage_ = this.gainStoreStructure(STRUCTURE_STORAGE,RESOURCE_ENERGY)
            if (this.ticksToLive > 20 &&storage_)
            this.withdraw__(storage_,RESOURCE_ENERGY)
            else this.harvest__(this.pos.findClosestByRange(FIND_SOURCES))
        }
    }
    /*
    ** A型2号
    ** 在所有墙体中，有墙体耐久低于500K时，选择广泛涂，高于500K时进行专注涂，涂rampart,wall
    */
    public repair_A2():void{
        this.workstate(RESOURCE_ENERGY)
        if (this.memory.working)
        {
            var leastRampart = this.room.getListHitsleast([STRUCTURE_RAMPART,STRUCTURE_WALL],3)
            if (!leastRampart) return
            if (leastRampart.hits < 500000)
            {
                this.repair__(leastRampart)
            }
            else
            {
                if (!this.memory.targetId || !Game.getObjectById(this.memory.targetId))
                    this.repair__(leastRampart)
                else
                {
                    var dis_wall = Game.getObjectById(this.memory.targetId) as Structure
                    this.repair__(dis_wall)
                }
            }
        }
        else
        {
            /* 寻找hits最小的墙 */
            var leastRam = this.room.getListHitsleast([STRUCTURE_RAMPART,STRUCTURE_WALL],3)
            if (!leastRam) return
            this.memory.targetId = leastRam.id
            var storage_ = this.gainStoreStructure(STRUCTURE_STORAGE,RESOURCE_ENERGY)
            if (storage_)
            this.withdraw__(storage_,RESOURCE_ENERGY)
            else this.harvest__(this.pos.findClosestByRange(FIND_SOURCES))
        }
        this.LastMisson(20)
    }





    /* 升级通用函数 */
    /* 搬运通用函数 */
    /* 防御通用函数 */
    /* 攻击通用函数 */
    /* 宣称、占领通用函数 */
}